package com.isoft.illustrationsdraw.service.impl;

import org.springframework.stereotype.Service;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.isoft.illustrationsdraw.entity.User;
import com.isoft.illustrationsdraw.service.AdminService;
import com.isoft.illustrationsdraw.service.JWTService;
import com.isoft.illustrationsdraw.service.RedisTokenService;
import com.isoft.illustrationsdraw.service.UserService;
import java.util.Date;

@Service
public class JWTServiceImpl implements JWTService {

    private static final String SECRET_KEY = "an-example-keyfduhaiufhoiHifuagtgfhasfuiahghg98y324hioY(o&*t*&y)";
    private static final long SHORT_EXPIRATION_TIME = 60 * 15; // 15分钟有效期
    private static final long LONG_EXPIRATION_TIME = 60 * 60 * 24 * 7; // 7天有效期

    private final UserService userService;
    private final RedisTokenService tokenService;
    private final AdminService adminService;

    public JWTServiceImpl(UserService userService, RedisTokenService tokenService, AdminService adminService) {
        this.userService = userService;
        this.tokenService = tokenService;
        this.adminService = adminService;
    }


    @Override
    public String generateLogInToken(String email) {
        User user = userService.getOrCreateUser(email);
        if (user == null || user.getId() == null) {
            throw new RuntimeException("Can't generate token for null id. This may due to database error.");
        }

        // if (user)

        Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);

        String token = JWT.create()
                .withSubject(user.getId().toString())    // 用户 ID
                .sign(algorithm);                  // 使用 HMAC256 算法进行签名
        
        tokenService.saveToken(token, SHORT_EXPIRATION_TIME);  // 将 token 保存到 Redis 中
        return token;
    }


    @Override
    public String generateLongTermToken(Long userId) {

        Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);

        return JWT.create()
                .withSubject(userId.toString())    // 用户 ID
                .withExpiresAt(new Date(System.currentTimeMillis() + LONG_EXPIRATION_TIME * 1000)) // 设置过期时间
                .sign(algorithm);                  // 使用 HMAC256 算法进行签名
    }

    // 解析令牌并返回 DecodedJWT 对象
    private DecodedJWT decodeToken(String token) {
        if (token == null) {
            return null;
        }
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET_KEY);
            return JWT.require(algorithm).build().verify(token);
        } catch (Exception e) {
            return null;
        }
    }

    @Override
    public Long getUserIdFromToken(String token) {
        DecodedJWT jwt = decodeToken(token);
        return jwt != null ? Long.parseLong(jwt.getSubject()) : null;
    }


    @Override
    public boolean validateToken(String token) {
        // 解析并验证 Token
        DecodedJWT jwt = decodeToken(token);
        if (jwt == null) {
            return false;  // 如果解码失败，返回无效
        }
    
        // 检查长期令牌是否过期
        Date expiresAt = jwt.getExpiresAt();
        if (expiresAt != null) {
            if (expiresAt.before(new Date())) {
                return false;  // 如果令牌已过期，返回无效
            }
            // 长期令牌未过期，直接返回有效
            return true;
        }
        // 检查短期令牌是否过期
        var savedTokenExpirationTime = tokenService.getTokenExpirationAndDelete(token);
        if (savedTokenExpirationTime == null || savedTokenExpirationTime <= 0) {
            return false;  // 如果令牌不存在或已经过期，返回无效
        }
    
        return true;  // 否则令牌有效
    }

    @Override
    public Date getLongTermTokenExpirationTime(String token) {
        DecodedJWT jwt = decodeToken(token);
        return jwt != null ? jwt.getExpiresAt() : null;
    }


    @Override
    public boolean isAdmin(String token) {
        Long userId = getUserIdFromToken(token);
        return adminService.getById(userId) == null ? false : true;
    }
    
}
